﻿using AutoMapper;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using XUCore.Ddd.Domain;
using XUCore.Extensions;
using XUCore.NetCore.FreeSql.Entity;

namespace XUCore.NetCore.FreeSql.Curd
{
    /// <summary>
    /// CURD服务
    /// </summary>
    /// <typeparam name="TKey">主键类型</typeparam>
    /// <typeparam name="TUkey">用户主键类型</typeparam>
    /// <typeparam name="TEntity">数据库实体</typeparam>
    /// <typeparam name="TDto">返回实体</typeparam>
    /// <typeparam name="TUser">IUser</typeparam>
    public abstract class UserCurdService<TKey, TUkey, TEntity, TDto, TUser> :
        CurdService<TKey, TUkey, TEntity, TDto>,
        IUserCurdService<TKey, TUkey, TEntity, TDto, TUser>
            where TEntity : EntityFull<TKey, TUkey>, new()
            where TDto : class, new()
            where TUser : IUser
    {
        /// <summary>
        /// 用户信息
        /// </summary>
        public readonly TUser user;
        /// <summary>
        /// CURD服务
        /// </summary>
        /// <param name="freeSql"></param>
        /// <param name="mapper"></param>
        /// <param name="user"></param>
        public UserCurdService(IFreeSql freeSql, IMapper mapper, TUser user)
            : base(freeSql, mapper)
        {
            this.user = user;
        }
        /// <summary>
        /// 设置更新的列<para></para>
        ///     注意：标记 [Column(CanUpdate = false)] 的属性不会被更新<para></para>
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="keyValues">var keyValues = new Dictionary&lt;string, object&gt;{ { "field1", 1 } , { "field2", "test" } };</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task<int> UpdateFieldAsync(TKey[] ids, Dictionary<string, object> keyValues, CancellationToken cancellationToken = default)
        {
            keyValues.AddIfNotContains(new KeyValuePair<string, object>(nameof(EntityFull<TKey, TUkey>.ModifiedAtUserId), user.GetId<TUkey>()));
            keyValues.AddIfNotContains(new KeyValuePair<string, object>(nameof(EntityFull<TKey, TUkey>.ModifiedAtUserName), user.Name));
            keyValues.AddIfNotContains(new KeyValuePair<string, object>(nameof(EntityFull<TKey, TUkey>.ModifiedAt), DateTime.Now));

            var res = await repo.UpdateDiy.WhereDynamic(ids)
                .SetDto(keyValues)
                .ExecuteAffrowsAsync(cancellationToken);

            FieldUpdatedAction?.Invoke(res > 0, ids, keyValues);

            return res;
        }
    }
}
